package com.tvserials.notification.parser;

import com.tvserials.notification.dto.Episode;
import com.tvserials.notification.dto.EpisodeMedia;
import com.tvserials.notification.dto.Serial;
import com.tvserials.notification.exceptions.NetworkConnectionException;
import com.tvserials.notification.exceptions.PageParseException;
import com.tvserials.notification.utils.VOUtils;
import com.tvserials.notification.vo.SourceType;
import com.tvserials.notification.vo.TvEpisodeFilterVO;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by oleksandr.dokienko on 5/12/2014.
 */
public class SeasonVarHtmlPageParser extends DefaultPageParser {
    public static final String MAIN_SEASONVAR_PAGE = "http://www.seasonvar.ru";
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss", Locale.ENGLISH);

    @Override
    protected List<Episode> parse(TvEpisodeFilterVO filterVO) throws NetworkConnectionException, PageParseException {
        Date latestSyncDate = filterVO.getLastSyncDate();
        List<Serial> serials = filterVO.getSerials();
        try {
            Connection connection = Jsoup.connect(MAIN_SEASONVAR_PAGE);
            connection.maxBodySize(Integer.MAX_VALUE);
            connection.header("User-Agent", "Mozilla/5.0");

            Document document = connection.timeout(20000).get();

            Elements items = document.select("body > div.main-center-block > " +
                    "div.content-center > div > table > tbody > tr > td.td-for-right-block > " +
                    "div.right-news-block").get(0).children();

            List<Episode> episodes = new ArrayList<Episode>();
            //TODO made temporal fix while we didn't move server
            List<Episode> rssList = parseRSS();
            if (rssList.isEmpty()) {
                return episodes;
            }
            for (Element element : items) {
                String titleStr = element.select("div > div > div.news-right > div > div:nth-child(1)").text();
                String chapterName = element.select("div.news-right-add").text();
                Date releaseDate = getPubDate(titleStr, chapterName, rssList);
                if (serials.contains(new Serial(titleStr, SourceType.SEASON_VAR))
                        && graterThan(latestSyncDate, releaseDate)) {
                    String link = MAIN_SEASONVAR_PAGE + element.select("a[href]").get(0).attr("href");
                    String imageUrl = element.select("img").attr("src");
                    Elements seasonElement = element.select("div > div > div.news-right > div > div:nth-child(3)");
                    String seasonNumber = seasonElement.text();

                    if (seasonNumber.equals(chapterName)) {
                        seasonNumber = null;
                    }

                    EpisodeMedia media = new EpisodeMedia();
                    media.setLink(link);
                    media.setSize("Open in browser");

                    Episode episode = new Episode();
                    episode.setShowName(new Serial(titleStr, SourceType.SEASON_VAR));
                    episode.setChapterDetailsUrl(link);
                    episode.setChapterName(chapterName);
                    episode.setChapterNumber(seasonNumber);
                    episode.setImage(VOUtils.loadImage(imageUrl));
                    episode.setReleaseDate(releaseDate);
                    episode.setMediaQualities(Arrays.asList(media));
                    episodes.add(episode);
                }
            }
            return episodes;
        } catch (IOException e) {
            throw new NetworkConnectionException(e);
        }
    }

    /**
     * TODO: The list of returned items is too big
     * Need to optimize somehow
     */
    @Override
    public List<Serial> parseSerialsList() throws NetworkConnectionException {
        try {
            Connection connection = Jsoup.connect(MAIN_SEASONVAR_PAGE);
            connection.header("User-Agent", "Mozilla/5.0");
            connection.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
            connection.maxBodySize(1024 * 1024 * 2);

            Document document = connection.timeout(20000).get();
            Elements elements = document.select("div.betterT");
            List<Serial> serials = new ArrayList<Serial>();
            for (Element item : elements) {
                String title = item.select("a").text();
                String link = MAIN_SEASONVAR_PAGE + item.select("a").attr("data");

                Serial serial = new Serial(title, SourceType.SEASON_VAR);
                serial.setLink(link);
                serials.add(serial);
            }
            return serials;
        } catch (IOException e) {
            throw new NetworkConnectionException(e);
        }
    }

    private Date getPubDate(String title, String chapterName, List<Episode> rssList) {
        for (Episode rssItem : rssList) {
            if (rssItem.getShowName().contains(title) &&
                    chapterName.equals(rssItem.getChapterName())) {
                return rssItem.getReleaseDate();
            }
        }
        return new Date();
    }

    private List<Episode> parseRSS() {
        try {
            Connection connection = Jsoup.connect(MAIN_SEASONVAR_PAGE + "/rss.php");
            Document document = connection.timeout(20000).get();

            Elements items = document.select("channel").select("item");

            List<Episode> episodes = new ArrayList<Episode>();
            for (Element element : items) {
                String titleStr = cleanText(element.getElementsByTag("title").text());
                String link = element.getElementsByTag("link").text();
                String dateStr = element.getElementsByTag("pubDate").text();
                Date date = getDate(dateStr);

                String title = titleStr.substring(0, titleStr.indexOf(","));
                String chapterDetail = titleStr.substring(titleStr.indexOf(",") + 1, titleStr.length()).trim();

                EpisodeMedia media = new EpisodeMedia();
                media.setLink(link);
                media.setSize(title);

                Episode episode = new Episode();
                episode.setShowName(new Serial(title, SourceType.SEASON_VAR));
                episode.setChapterDetailsUrl(link);
                episode.setReleaseDate(date);
                episode.setChapterName(chapterDetail);
                episode.setMediaQualities(Arrays.asList(media));
                episodes.add(episode);
            }
            return episodes;
        } catch (IOException e) {
            // do nothing
        }
        return new ArrayList<Episode>();
    }

    private String cleanText(String text) {
        if (text != null) {
            return text.replace("<![CDATA", "").replace("]]>", "");
        }
        return "";
    }

    private Date getDate(String dateStr) {
        try {
            return simpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public SourceType getSourceType() {
        return SourceType.SEASON_VAR;
    }
}
